/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.google.code.morphia.jaxb2;

import com.sun.codemodel.JClass;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JFieldRef;
import com.sun.codemodel.JFieldVar;
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JPackage;
import com.sun.codemodel.JTypeVar;
import com.sun.tools.xjc.Options;
import com.sun.tools.xjc.Plugin;
import com.sun.tools.xjc.addon.code_injector.Const;
import com.sun.tools.xjc.model.CCustomizations;
import com.sun.tools.xjc.model.CPluginCustomization;
import com.sun.tools.xjc.outline.ClassOutline;
import com.sun.tools.xjc.outline.Outline;
import com.sun.tools.xjc.util.DOMUtils;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.NamedNodeMap;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;

/**
 * Jaxb2 Plugin to support generating
 * 
 * TODO: Generate DAO's ...
 * TODO: Support for Set/HashSet ... -> jaxb only supports List
 * TODO: Write Tests ... Use TestCase as explaining example
 * 
 * @author Henning Kropp
 */
public class MorphiaPlugin extends Plugin {

  private final Log log = LogFactory.getLog(getClass());
  public static final String NS = "http://jaxb.dev.java.net/plugin/morphia-jaxb2";

  /**
   * 
   * @return 
   */
  @Override
  public String getOptionName() {
    return "Xmorphia";
  }

  /**
   * 
   * @return 
   */
  @Override
  public String getUsage() {
    return "  -Xmorphia      :  ToDo: Explain Usage"; // TODO
  }

  /**
   * 
   * @return 
   */
  @Override
  public List<String> getCustomizationURIs() {
    return Collections.singletonList(MorphiaPlugin.NS);
  }

  /**
   * 
   * @param nsUri
   * @param localName
   * @return 
   */
  @Override
  public boolean isCustomizationTagName(String nsUri, String localName) {
    return nsUri.equals(MorphiaPlugin.NS) && localName.equals("objectId");
  }

  /**
   * TODO: seperate method createObjId
   * TODO: attribute if objId private (getter+setter) or public (no getter+setter) (??)
   * 
   * @param outline
   * @param opt
   * @param eh
   * @return
   * @throws SAXException 
   */
  @Override
  public boolean run(Outline outline, Options opt, ErrorHandler eh) throws SAXException {
    for (ClassOutline co : outline.getClasses()) {
      CPluginCustomization c = co.target.getCustomizations().find(MorphiaPlugin.NS, "objectId");
      if (c == null) {
        continue;
      }
      c.markAsAcknowledged();

      // objId w/ getter + setter
      JFieldVar field = co.implClass.field(4,org.bson.types.ObjectId.class , "objId");
      field.annotate(com.google.code.morphia.annotations.Id.class);
      field.annotate(javax.xml.bind.annotation.XmlTransient.class);
      JMethod getObjIdMethod = co.implClass.method(1, org.bson.types.ObjectId.class, "getObjId");
      getObjIdMethod.body()._return(field);
      JMethod setObjIdMethod = co.implClass.method(1,void.class, "setObjId");
      setObjIdMethod.param(org.bson.types.ObjectId.class, "objId");
      setObjIdMethod.body().assign(JExpr.refthis("objId"), field);
    }
    return true;
  }
}
